package com.hotel.dao;

import java.text.ParseException;
import java.util.Date;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Property;
import org.hibernate.criterion.Restrictions;
import org.hibernate.criterion.Subqueries;

import com.hotel.entidade.Hospedagem;
import com.hotel.entidade.Quarto;
import com.hotel.entidade.Reserva;

public class ReservaDAO {

	private Session session;

	public ReservaDAO(Session session) {
		this.session = session;
	}
	
	public void insere(Reserva reserva) {
		session.save(reserva);
		session.beginTransaction().commit();
		session.close();
	}

	public void deleta(Reserva reserva) {
		session.delete(reserva);
		session.beginTransaction().commit();
	}

	public void atualisa(Reserva reserva) {
		session.update(reserva);
		session.beginTransaction().commit();
	}

	public Reserva buscaPorId(int id) {
		return (Reserva) session.load(Reserva.class, id);
	}

	@SuppressWarnings("unchecked")
	public List<Reserva> pesquisarReserva(String keyword){
		Criteria c = session.createCriteria(Reserva.class)  
			.createAlias("hospede", "hospede")
			.add(Restrictions.ilike("hospede.nome", keyword, MatchMode.ANYWHERE));
		List<Reserva> list = c.addOrder(Order.desc("status")).list();
		return list;
	}

	@SuppressWarnings("unchecked")
	public List<Reserva> listaTodos() {
		return session.createCriteria(Reserva.class).addOrder(Order.desc("status")).list();
	}
	
	public boolean verificaDisponibilidade(Date ini, Date fim) throws ParseException{
		boolean disponivel = true;
		@SuppressWarnings("unchecked")
		List<Reserva> list = session.createCriteria(Reserva.class)
			.add(Restrictions.and(
				Restrictions.le("dataInicio", fim),
				Restrictions.ge("dataFim", ini)))
			.list();
		
		if(list.size()>0){
			disponivel = false;
		}
		return disponivel;
	}
	
	@SuppressWarnings("unchecked")
	public List<Quarto> quartosDisp(Date ini, Date fim) {
		Criteria criteria = session.createCriteria(Quarto.class)
				.add(Restrictions.and(
					Subqueries.propertyNotIn("codigo", DetachedCriteria.forClass(Hospedagem.class)
						.add(Restrictions.and(
								Restrictions.le("dataInicio", fim),
								Restrictions.ge("dataFim", ini),
								Restrictions.eq("status", true)
							)
						)
						.createAlias("quarto", "quarto")
						.setProjection(Property.forName("quarto.codigo"))
					),
					Subqueries.propertyNotIn("codigo", DetachedCriteria.forClass(Reserva.class)
						.add(Restrictions.and(
								Restrictions.le("dataInicio", fim),
								Restrictions.ge("dataFim", ini),
								Restrictions.eq("status", true)
							)
						)
						.createAlias("quarto", "quarto")
						.setProjection(Property.forName("quarto.codigo"))
				)));
		List<Quarto> list = criteria.list();
		return list;
	}
	
	public void hospedar(Hospedagem hospedagem) {
		session.save(hospedagem);
		session.beginTransaction().commit();
	}
	
}